﻿using System;
using System.Collections.Concurrent;
using System.Security.Claims;
using System.Threading;
using Microsoft.Extensions.Caching.Memory;

namespace Flies.SQLSugarCore
{

    public static class LoginInfoStore
    {
        // 双重缓存机制：内存缓存 + 静态字典
        private static readonly ConcurrentDictionary<string, CachedUserInfo> _activeUsers =
            new ConcurrentDictionary<string, CachedUserInfo>(StringComparer.OrdinalIgnoreCase);

        // 缓存过期策略（可配置）
        private static readonly MemoryCache _userCache = new MemoryCache(new MemoryCacheOptions
        {
            SizeLimit = 10000, // 最大缓存条目
            ExpirationScanFrequency = TimeSpan.FromMinutes(5)
        });

        // 缓存配置
        private static readonly MemoryCacheEntryOptions _cacheOptions = new MemoryCacheEntryOptions
        {
            SlidingExpiration = TimeSpan.FromMinutes(20),
            Size = 1,
            PostEvictionCallbacks = { new PostEvictionCallbackRegistration
        {
            EvictionCallback = (key, value, reason, state) =>
            {
                if (key is string userId)
                {
                    _activeUsers.TryRemove(userId, out _);
                }
            }
        }}
        };

        /// <summary>
        /// 存储登录信息
        /// </summary>
        public static void SetUserInfo(UserSessionInfo sessionInfo)
        {
            if (sessionInfo == null) throw new ArgumentNullException(nameof(sessionInfo));

            var cacheKey = GetCacheKey(sessionInfo.UserId);

            // 创建缓存项
            var userInfo = new CachedUserInfo
            {
                Claims = new ClaimsIdentity(sessionInfo.Claims),
                LastActivity = DateTime.UtcNow,
                SessionId = sessionInfo.SessionId
            };

            // 双重存储
            _userCache.Set(cacheKey, userInfo, _cacheOptions);
            _activeUsers[cacheKey] = userInfo;

            // 更新全局用户计数
            Interlocked.Increment(ref _activeUserCount);
        }

        /// <summary>
        /// 获取用户信息
        /// </summary>
        public static UserSessionInfo GetUserInfo(string userId)
        {
            var cacheKey = GetCacheKey(userId);

            // 首先尝试从缓存获取
            if (_userCache.TryGetValue(cacheKey, out CachedUserInfo cachedInfo))
            {
                // 更新最后活动时间
                cachedInfo.LastActivity = DateTime.UtcNow;
                return MapToSessionInfo(cachedInfo);
            }

            // 其次尝试从静态字典获取（防止缓存失效但会话仍存在）
            if (_activeUsers.TryGetValue(cacheKey, out cachedInfo))
            {
                // 重新加入缓存
                _userCache.Set(cacheKey, cachedInfo, _cacheOptions);
                return MapToSessionInfo(cachedInfo);
            }

            return null;
        }

        /// <summary>
        /// 移除用户信息（登出时调用）
        /// </summary>
        public static void RemoveUserInfo(string userId)
        {
            var cacheKey = GetCacheKey(userId);
            _userCache.Remove(cacheKey);
            _activeUsers.TryRemove(cacheKey, out _);

            // 更新全局用户计数
            Interlocked.Decrement(ref _activeUserCount);
        }

        // 获取当前活跃用户数
        private static long _activeUserCount;
        public static long ActiveUserCount => Interlocked.Read(ref _activeUserCount);

        // 关键内部方法
        private static string GetCacheKey(string userId) => $"UserInfo_{userId}";

        private static UserSessionInfo MapToSessionInfo(CachedUserInfo cachedInfo) =>
            new UserSessionInfo
            {
                UserId = cachedInfo.Claims.FindFirst(ClaimTypes.NameIdentifier)?.Value,
                Claims = cachedInfo.Claims.Claims,
                LastActivity = cachedInfo.LastActivity,
                SessionId = cachedInfo.SessionId
            };

        // 内部缓存结构
        private class CachedUserInfo
        {
            public ClaimsIdentity Claims { get; set; }
            public DateTime LastActivity { get; set; }
            public string SessionId { get; set; }
        }
    }

    // 登录信息DTO
    public class UserSessionInfo
    {
        public string UserId { get; set; }
        public IEnumerable<Claim> Claims { get; set; }
        public DateTime LastActivity { get; set; }
        public string SessionId { get; set; }
    }

}
